{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Python 中没有像 C++ 表示的字符类型（char），所有的字符或串都被统一为 `str` 对象。如单个字符 `c` 的类型也为 `str`，因此在python中**字符也就是字符串**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "str 类型会被经常使用，一些高频用法如下"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 字符串去空格"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'I love python'"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "'  I love python  '.strip()\n",
    "# 'I love python'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 字符串替换"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'i_love_python'"
      ]
     },
     "execution_count": 73,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 替换所有的字符\n",
    "'i love python'.replace(' ','_')\n",
    "# 'i_love_python'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# join串联字符串"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'book_store_count'"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "'_'.join(['book', 'store','count'])\n",
    "# 'book_store_count'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 使用字符串的find方法返回匹配字符串的起始位置索引"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "7"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "'i love python'.find('python')\n",
    "# 7"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 反转字符串"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'nohtyp'"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 发1\n",
    "s = \"python\"\n",
    "rs = ''.join(reversed(s))\n",
    "rs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'nohtyp'"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s[::-1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[6, 5, 2, 3, 1]"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = [1,3,2,5,6]\n",
    "list(reversed(a))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 字符串切片操作"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "只要是列表能用的切片，字符串都能用"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'2345'"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s = '123456'\n",
    "s[1:5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'24'"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s[1:5:2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'642'"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s[::-2]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 分割字符串"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "根据指定字符或字符串，分割一个字符串时，使用方法 split。\n",
    "\n",
    "join 和 split 可看做一对互逆操作"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['I', 'love', 'python']"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "'I_love_python'.split('_')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 子串判断"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "判断 a 串是否为 b 串的子串。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = 'abc'\n",
    "b = 'mnabcdf'\n",
    "a in b"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用方法 find，返回字符串 b 中匹配子串 a 的最小索引\n",
    "\n",
    "str的find方法与list的index方法用途一样"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b.find(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 正则表达式"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "字符串封装的方法，处理一般的字符串操作，还能应付。但是，稍微复杂点的字符串处理任务，需要靠正则表达式，简洁且强大。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "首先，导入所需要的模块 re"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "import re"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "认识常用的**元字符**：\n",
    "\n",
    "- `.` 匹配除 \"\\n\" 和 \"\\r\" 之外的任何单个字符。\n",
    "- `^` 匹配字符串开始位置\n",
    "- `$` 匹配字符串中结束的位置\n",
    "- `*` 前面的原子重复 0 次、1 次、多次\n",
    "- `?` 前面的原子重复 0 次或者 1 次\n",
    "- `+` 前面的原子重复 1 次或多次\n",
    "- `{n}` 前面的原子出现了 n 次\n",
    "- `{n,}` 前面的原子至少出现 n 次\n",
    "- `{n,m}` 前面的原子出现次数介于 n-m 之间\n",
    "- `( )` 分组，输出需要的部分"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "再认识常用的**通用字符**："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- `\\s` 匹配空白字符\n",
    "- `\\w` 匹配任意字母/数字/下划线\n",
    "- `\\W` 和小写 w 相反，匹配任意字母/数字/下划线以外的字符\n",
    "- `\\d` 匹配十进制数字\n",
    "- `\\D` 匹配除了十进制数以外的值\n",
    "- `[0-9]` 匹配一个 0~9 之间的数字\n",
    "- `[a-z]` 匹配小写英文字母\n",
    "- `[A-Z]` 匹配大写英文字母"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "正则表达式，常会涉及到以上这些元字符或通用字符，下面是一些使用方式和小技巧"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## search 第一个匹配串"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(7, 11)"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import re\n",
    "s = 'I am a good student'\n",
    "pat = 'good'\n",
    "r = re.search(pat,s)\n",
    "# 返回子串的起始位置和终止位置\n",
    "r.span()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## match匹配字符串开始位置"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "正则模块中，match、search 方法匹配字符串不同\n",
    "\n",
    "- match 在原字符串的开始位置匹配\n",
    "- search 在字符串的任意位置匹配"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用match方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "ename": "AttributeError",
     "evalue": "'NoneType' object has no attribute 'span'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mAttributeError\u001b[0m                            Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-44-cf005ee8a96a>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m      3\u001b[0m \u001b[0mpat\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;34m'wor'\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      4\u001b[0m \u001b[0mr\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mre\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mmatch\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mpat\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0ms\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 5\u001b[1;33m \u001b[0mr\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mspan\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mAttributeError\u001b[0m: 'NoneType' object has no attribute 'span'"
     ]
    }
   ],
   "source": [
    "import re\n",
    "s = 'helloworld'\n",
    "pat = 'wor'\n",
    "r = re.match(pat,s)\n",
    "r.span()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用 search 方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(5, 8)"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import re\n",
    "s = 'helloworld'\n",
    "pat = 'wor'\n",
    "r = re.search(pat,s)\n",
    "r.span()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "现在，把子串`wor`放在最前面，再使用match匹配"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0, 3)"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s = 'world'\n",
    "pat = 'wor'\n",
    "r = re.match(pat,s)\n",
    "r.span()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## finditer匹配迭代器"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用正则模块，finditer 方法，**返回所有子串匹配位置的迭代器**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "通过返回的对象 `re.Match`，使用它的方法 span 找出匹配位置"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<re.Match object; span=(2, 3), match='a'>\n",
      "<re.Match object; span=(5, 6), match='a'>\n"
     ]
    }
   ],
   "source": [
    "s = 'I am a good student'\n",
    "pat = 'a'\n",
    "r = re.finditer(pat,s)\n",
    "for i in r:\n",
    "    print(i)\n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## findall 所有匹配"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "正则模块，findall 方法能查找出子串的所有匹配。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "注意：\n",
    " - `findall`是返回所有的匹配\n",
    " - `finditer`是返回所有匹配的位置\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {},
   "outputs": [],
   "source": [
    "s = '呼叫战狼,我是8371,请您在9.56秒后回到3号机场'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "目标查找出所有所有数字：通用字符 `\\d` 匹配一位数字 [0-9]，`+` 表示匹配数字前面的一个字符 1 次或多次。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "不带元字符`+`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['8', '3', '7', '1', '9', '5', '6', '3']\n"
     ]
    }
   ],
   "source": [
    "pat = r'\\d'\n",
    "r = re.findall(pat,s)\n",
    "print(r)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "带上元字符`+`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['8371', '9', '56', '3']\n"
     ]
    }
   ],
   "source": [
    "pat = r'\\d+'\n",
    "r = re.findall(pat,s)\n",
    "print(r)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`re.findall`返回一个列表，里面包含四个数字，可以看到里面没有小数点，如果我们要找到`9.56`，应该怎么做呢？"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 匹配浮点数和整数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 元字符`?` 表示前一个字符匹配 0 或 1 次\n",
    "- 元字符`.?` 表示匹配小数点（`.`）0 次或 1 次。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "匹配浮点数和整数，我们先来看正则表达式：`r'\\d+\\.?\\d+'`，该正则表达式可以理解为：先匹配1个或多个数字，再匹配小数点（`.`）0 次或 1 次，最后匹配1个或多个数字，分解演示如下："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![img](img/img1.jpg)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['8371', '9.56']"
      ]
     },
     "execution_count": 77,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s = '呼叫战狼,我是8371,请您在9.56秒后回到3号机场'\n",
    "pat = r'\\d+\\.?\\d+'\n",
    "r = re.findall(pat,s)\n",
    "r"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以看到，没有匹配到3，哪里出错了呢？"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "出现问题原因：`r'\\d+\\.?\\d+'`， 前面的`\\d+` 表示至少有一位数字，后面的`\\d+`也表示至少有一位数字，因此，整个表达式至少会匹配两位数。\n",
    "\n",
    "现在将最后的 `+` 后修改为 `*`，表示匹配前面字符 0 次、1 次或多次。如下所示："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![img](img/img2.jpg)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['8371', '9.56', '3']"
      ]
     },
     "execution_count": 82,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s = '呼叫战狼,我是8371,请您在9.56秒后回到3号机场'\n",
    "pat = r'\\d+\\.?\\d*'\n",
    "r = re.findall(pat,s)\n",
    "r"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "到这里就大功完成了，到这里我们再思考一下，如果把`.?`前面的`\\`去掉以后会怎么样？如下："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['8371,', '9.56', '3号']"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s = '呼叫战狼,我是8371,请您在9.56秒后回到3号机场'\n",
    "pat = r'\\d+.?\\d*'\n",
    "r = re.findall(pat,s)\n",
    "r"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以看到，匹配到了一个汉字，为什么会出现这种情况呢？因为这里`.?`的含义就变了，之前是把`\\.?`作为一个整体，现在`.?`的含义是附加到`\\d.?`上。\n",
    "\n",
    "\n",
    "`\\d+.?\\d`中`.?`含义如下：\n",
    "- `.` 匹配除 \"\\n\" 和 \"\\r\" 之外的任何单个字符。\n",
    "- 那`.?`就表示匹配\"\\n\" 和 \"\\r\" 之外的任何单个字符0 次或 1 次。\n",
    "\n",
    "我们看下演示图就知道了，`\\d+.?\\d`的演示图如下"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![img](img/img3.jpg)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 匹配正整数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "案例：**写出匹配所有正整数的正则表达式**\n",
    "\n",
    "我们先来看几个正则表达式即它们的含义\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "前面讲过"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- `\\d+` 表示数字出现1次或多次\n",
    "- `\\d*` 表示数字出现0次或多次"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1. `\\d*` 表示数字出现0次或多次，也就是会匹配所有的字符"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, '我是1', '1是我', '123', 0, 3, '已经9.56秒了', 10, -1]"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s = [2,'我是1','1是我','123',0, 3,'已经9.56秒了',10,-1]\n",
    "pat = r'\\d*'\n",
    "[i for i in s if re.match(pat,str(i))]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "2. `^\\d*$`,在数字出现0次或多次前加上了开始位置，再后加上了结束位置。即必须是以数字的开头，以数字结尾，才能匹配到"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![img](img/img4.jpg)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, '123', 0, 3, 10]"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s = [2,'我是1','1是我','123',0, 3,'已经9.56秒了',10,-1]\n",
    "pat =r'^\\d*$'\n",
    "[i for i in s if re.match(pat,str(i))]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以看到，匹配到了0，我们的目的是匹配所有正整数，所以不正确"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "3. `^[1-9]*$` 表示匹配一个 0~9 之间的数字"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, '123', 3]"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s = [2,'我是1','1是我','123',0, 3,'已经9.56秒了',10,-1]\n",
    "pat =r'^[1-9]*$'\n",
    "[i for i in s if re.match(pat,str(i))]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以看到，不能匹配10，因此这个也不正确"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "4. `^[1-9]\\d*$` 表示匹配一个 0~9 之间的数字并且匹配的数字出现0次或多次"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![img](img/img5.jpg)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, '123', 3, 10]"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s = [2,'我是1','1是我','123',0, 3,'已经9.56秒了',10,-1]\n",
    "pat =r'^[1-9]\\d*$'\n",
    "[i for i in s if re.match(pat,str(i))]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## re.I 忽略大小写"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "找出字符串中所有字符 t 或 T 的位置，不区分大小写。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(2, 3)\n",
      "(3, 4)\n",
      "(9, 10)\n"
     ]
    }
   ],
   "source": [
    "s = 'HELLO，World'\n",
    "pat = 'L'\n",
    "r = re.finditer(pat,s,re.I)\n",
    "for i in r:\n",
    "    print(i.span())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['L', 'L', 'l']"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s = 'HELLO，World'\n",
    "pat = 'L'\n",
    "r = re.findall(pat,s,re.I)\n",
    "r"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## split分割单词"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**正则模块中 split 函数强大，能够处理复杂的字符串分割任务**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "对于简单的分割，直接用分隔符"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['I', 'am', 'a', 'good', 'student']"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s = 'I-am-a-good-student'\n",
    "s.split('-')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "但是，对于分隔符复杂的字符串，split 函数就无能为力\n",
    "\n",
    "如下字符串，可能的分隔符有`, ; - . |`和空格"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['I,,,am |  ;a - good.. student']"
      ]
     },
     "execution_count": 68,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s = 'I,,,am |  ;a - good.. student'\n",
    "s.split('[,;\\-.|]')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以看到，直接使用是区分不开的，所有可以用正则模块中的split"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`\\s` 匹配空白字符"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['I', 'am', 'a', 'good', 'student']"
      ]
     },
     "execution_count": 71,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\n",
    "s = 'I,,,am |  ;a - good.. student'\n",
    "w = re.split(r'[,.\\s;\\-|]+',s)\n",
    "w"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## sub 替换匹配串"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "正则模块，sub 方法，替换匹配到的子串"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'你好，我是hello'"
      ]
     },
     "execution_count": 75,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s = '你好，我是12306'\n",
    "pat = r'\\d+'\n",
    "w = re.sub(pat,'hello',s)\n",
    "w"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## compile 预编译"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果要用同一匹配模式，做很多次匹配，可以使用 compile 预先编译串"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果我们要：从一系列字符串中，挑选出所有正浮点数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "正则表达式为：`^[1-9]\\d*\\.\\d*|0\\.\\d*[1-9]\\d*$`，字符 `a|b `表示 `a` 串匹配失败后，才执行 `b` 串"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[7.21, 0.5, '3.25', 11.0, 9.0]"
      ]
     },
     "execution_count": 81,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s = [-1,10,0,7.21,0.5,'123','你好','3.25',11.0,9.]\n",
    "rec = re.compile(r'^[1-9]\\d*\\.\\d*|0\\.\\d*[1-9]\\d*$')\n",
    "[ i for i in s if rec.match(str(i))]"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  },
  "toc-autonumbering": true
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
